/**************************************************************************
 * @file usr_adc_handle.c
 * @author BryanHe(贺璧) (532352406@qq.com)
 * @brief 
 * @version 0.1
 * @date 2024-11-11
 * 
 * @copyright Copyright (c) 2024
 * 
 *************************************************************************/
#include "usr_adc_handle.h"
static uint16_t adc1_ordinary_value = 0;
static mo_u8 mcu_tem_adc_trigger;
static mo_u8 mcu_adc_err;
static int mcu_temp=25;
mo_u8 temp_adc_dam_flg=0;
cycle_buf_dat_t cyc_dat={0};

static void put_dat_to_cycle_buf(cycle_buf_dat_t *dat_t,mo_u16 adc_v){

    dat_t->mcu_adc_cycle_buf[dat_t->start_index]=adc_v;
    dat_t->start_index++;
    dat_t->start_index%=MCU_ADC_CYCLE_BUF_SIZE;
    if(dat_t->active_dats<MCU_ADC_CYCLE_BUF_SIZE)dat_t->active_dats++;
    
}
static mo_u32 get_average_value_from_cycle_buf(cycle_buf_dat_t *dat_t){
    mo_u32 sum=0,avg;

    for (size_t i = 0; i < dat_t->active_dats; i++){
        sum += dat_t->mcu_adc_cycle_buf[i];
    }
    avg =sum/dat_t->active_dats;

    return avg;  
}

/**
 * @brief  dma configuration.
 * @param  none
 * @retval none
 */
static void dma_config(void) {
    #if 0
    dma_init_type dma_init_struct;
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    dma_reset(DMA1_CHANNEL1);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = 1;
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_base_addr = (uint32_t)&adc1_ordinary_value;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
    dma_init_struct.memory_inc_enable = FALSE;
    dma_init_struct.peripheral_base_addr = (uint32_t) & (ADC1->odt);
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = TRUE;
    dma_init(DMA1_CHANNEL1, &dma_init_struct);

    dma_channel_enable(DMA1_CHANNEL1, TRUE);
    #else
    dma_init_type dma_init_struct;
  crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
  dma_reset(DMA1_CHANNEL1);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.buffer_size = 1;
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_base_addr = (uint32_t)&adc1_ordinary_value;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
  dma_init_struct.memory_inc_enable = FALSE;
  dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt);
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_HIGH;
  dma_init_struct.loop_mode_enable = TRUE;
  dma_init(DMA1_CHANNEL1, &dma_init_struct);

  dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
  dma_channel_enable(DMA1_CHANNEL1, TRUE);
    #endif
}

/**
 * @brief  adc configuration.
 * @param  none
 * @retval none
 */
static void adc_config(void) {
    adc_base_config_type adc_base_struct;
    crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
    crm_adc_clock_div_set(CRM_ADC_DIV_6);

    adc_base_default_para_init(&adc_base_struct);
    adc_base_struct.sequence_mode = FALSE;
    adc_base_struct.repeat_mode = FALSE;
    adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
    adc_base_struct.ordinary_channel_length = 1;
    adc_base_config(ADC1, &adc_base_struct);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_16, 1, ADC_SAMPLETIME_239_5);
    adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
    adc_dma_mode_enable(ADC1, TRUE);
    adc_tempersensor_vintrv_enable(TRUE);

    adc_enable(ADC1, TRUE);
    adc_calibration_init(ADC1);
    while (adc_calibration_init_status_get(ADC1));
    adc_calibration_start(ADC1);
    while (adc_calibration_status_get(ADC1));
}
/**************************************************************************
 * @brief Get the mcu temp object
 * 
 * @param tmp_buf 指向接受温度值的buffer
 * @return int -1: The ADC value not ready or Error, 0: The ADC value is ready
 *************************************************************************/
int get_mcu_temp(int *tmp_buf){
    int ret=0;
    mo_u16 adc_dat;

    if(tmp_buf==NULL)ret = -1;
        
    if(temp_adc_dam_flg){
        put_dat_to_cycle_buf(&cyc_dat,adc1_ordinary_value);
        adc_dat = get_average_value_from_cycle_buf(&cyc_dat);
        *tmp_buf = GET_MCU_TEMP(adc_dat);
        USR_DBG_INFO("dma_int_cnt:%d, temp %f deg C\r\n",temp_adc_dam_flg,GET_MCU_TEMP(adc1_ordinary_value));
        temp_adc_dam_flg=0;
        adc_ordinary_software_trigger_enable(ADC1, TRUE);
    }else{
        mcu_adc_err++;
        if(mcu_adc_err >9 ){
            adc_ordinary_software_trigger_enable(ADC1, TRUE);
            USR_DBG_INFO("Timeout error\r\n");
        }
        ret = -1;
    } 
    
    return ret;
}

void mcu_temperature_adc_init(void){
    dma_config();
    adc_config();
    adc_ordinary_software_trigger_enable(ADC1, TRUE);
    mcu_tem_adc_trigger=0;
    mcu_adc_err=0;
}
/**************************************************************************
 * @brief Get the mcu temp str by tmp value object
 * 
 * @param tmp 
 * @param str_len 
 * @param str_buf 
 * @return int 
 *************************************************************************/
int get_mcu_temp_str_by_tmp_value(int tmp,mo_u8 str_len,mo_u8 *str_buf){
    mo_u16 t;
    mo_u8 *dat2;

    if(str_buf==NULL)return -1;

    if(tmp>=0){
        t = tmp;
        strcat(str_buf," ");
    }else{
        t=tmp*-1;
        strcat(str_buf,"-");
    }
    dat2 = &str_buf[1];
    get_string_by_number(t,dat2,str_len,1);

    return 0;
}
/**************************************************************************
 * @brief 
 * 
 *************************************************************************/
void mcu_temperature_handle(void){
    // int temp;
    static mo_u8 cnt=0;

    mo_u16 t;
    mo_u8 *dat,*dat2;
    #define BUF_MCU_TEMP_SIZE_ 32ul

    cnt++;

    if(cnt > 9){
        cnt=0;
        if(get_mcu_temp(&mcu_temp)==0){
            dat = (mo_u8*)mo_malloc(BUF_MCU_TEMP_SIZE_);
            if(dat!=NULL){
                memset(dat,0,BUF_MCU_TEMP_SIZE_);
                get_mcu_temp_str_by_tmp_value(mcu_temp,3,dat);
                mo_msg_send(get_usr_display_task(),USR_MCU_TEMPERATURE_UPDATE,dat,0);
            }
        }
    }
    
}

int get_mcu_temp_value(void){
    return mcu_temp;
}
